package com.jindy.module.approvalRecord.service.impl;

import com.alibaba.fastjson2.JSON;
import com.jindy.common.constant.Constants;
import com.jindy.common.constant.HttpStatus;
import com.jindy.common.core.domain.AjaxResult;
import com.jindy.common.core.domain.model.LoginUser;
import com.jindy.common.exception.base.BaseException;
import com.jindy.common.utils.DateUtils;
import com.jindy.common.utils.SecurityUtils;
import com.jindy.jpush.domain.UniPushDomain;
import com.jindy.jpush.utils.JPushUtils;
import com.jindy.jpush.utils.UniJpushUtils;
import com.jindy.module.additionalDeposit.service.ISyAdditionalDepositService;
import com.jindy.module.approvalConfig.domain.ApprovalConfig;
import com.jindy.module.approvalConfig.mapper.ApprovalConfigMapper;
import com.jindy.module.approvalRecord.domain.ApprovalRecord;
import com.jindy.module.approvalRecord.mapper.ApprovalRecordMapper;
import com.jindy.module.approvalRecord.service.IApprovalRecordService;
import com.jindy.module.jpush.mapper.JpushMapper;
import com.jindy.module.order.service.impl.OrderServiceImpl;
import com.jindy.module.outboundorder.service.IOutboundOrderService;
import com.jindy.module.syTableRecord.service.ISyTableRecordTService;
import com.jindy.ws.po.Message;
import com.jindy.ws.service.WebSocketServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 审批记录Service业务层处理
 * 
 * @author jindy
 * @date 2023-03-28
 */
@Service
public class ApprovalRecordServiceImpl implements IApprovalRecordService 
{
    private static final Logger LOGGER = LoggerFactory.getLogger(ApprovalRecordServiceImpl.class);

    public static final String SHI_YU = "湿云";

    @Resource
    private ApprovalRecordMapper approvalRecordMapper;

    /**
     * 消息推送
     */
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 第三方消息推送
     */
    @Autowired
    private JPushUtils jPushUtils;

    /**
     * 消息推送配置表
     */
    @Resource
    private JpushMapper jpushMapper;

    /**
     *配置表
     */
    @Resource
    private ApprovalConfigMapper approvalConfigMapper;

    /**
     * 出货订单service
     */
    @Resource
    private IOutboundOrderService outboundOrderService;

    /**
     * 追加押金 service
     */
    @Resource
    private ISyAdditionalDepositService iSyAdditionalDepositService;

    /**
     * 记录表Service
     */
    @Resource
    private ISyTableRecordTService iSyTableRecordTService;

    /**
     * orderService
     */
    @Resource
    private OrderServiceImpl orderServiceImpl;


    /**
     * 查询审批记录
     * 
     * @param id 审批记录主键
     * @return 审批记录
     */
    @Override
    public ApprovalRecord selectApprovalRecordById(Long id)
    {
        return approvalRecordMapper.selectApprovalRecordById(id);
    }

    /**
     * 查询审批记录列表
     * 
     * @param approvalRecord 审批记录
     * @return 审批记录
     */
    @Override
    public List<ApprovalRecord> selectApprovalRecordList(ApprovalRecord approvalRecord)
    {
        return approvalRecordMapper.selectApprovalRecordList(approvalRecord);
    }

    /**
     * 新增审批记录
     * 
     * @param approvalRecord 审批记录
     * @return 结果
     */
    @Override
    public int insertApprovalRecord(ApprovalRecord approvalRecord)
    {
        approvalRecord.setCreateTime(DateUtils.getNowDate());
        return approvalRecordMapper.insertApprovalRecord(approvalRecord);
    }

    /**
     * 修改审批记录
     * 
     * @param approvalRecord 审批记录
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateApprovalRecord(ApprovalRecord approvalRecord)
    {
        //校验是否登录
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser==null){
            return new AjaxResult(HttpStatus.UNAUTHORIZED,"请先登录");
        }
        List<ApprovalRecord> currApprovalRecords=null;
        //获取当前审批记录：根据流水单号，审批状态，审批人获取审批信息
        if (!Constants.RECALL.equals(approvalRecord.getTypeOperation())){
            currApprovalRecords = approvalRecordMapper.selectApprovalRecordList(new ApprovalRecord(approvalRecord.getSerialNum(),loginUser.getUserId(),Constants.APPROVE));
            if (CollectionUtils.isEmpty(currApprovalRecords)){
                return new AjaxResult(HttpStatus.ERROR,"您不是当前审批人或该审批记录异常");
            }
        }

        //获取该流水单号的所有审批记录
        List<ApprovalRecord> allApprovalRecords = getApprovalRecords(approvalRecord);
        if (CollectionUtils.isEmpty(allApprovalRecords)){
            return new AjaxResult(HttpStatus.ERROR,"审批记录的所有记录为空");
        }
        //操作同意
        if (Constants.AGREE.equals(approvalRecord.getTypeOperation())){
            //修改当前流程记录状态：审批中->已完成
            ApprovalRecord approvalRecordParam = getApprovalRecord(approvalRecord,loginUser, currApprovalRecords,Constants.COMPLETED,Constants.AGREE);
            approvalRecordMapper.updateApprovalRecordBySerialNum(approvalRecordParam);
            //该流水单号所有记录条数与当前记录序号对比，相等则审批为最后一个节点
            if (allApprovalRecords.size()!=currApprovalRecords.get(0).getSequence()){
                //    修改下一节点状态为审批中
                ApprovalRecord nextNodeRecord = new ApprovalRecord();
                nextNodeRecord.setApprovalStatus(Constants.APPROVE);
                Integer sequence = currApprovalRecords.get(0).getSequence()+1;
                nextNodeRecord.setSequence(sequence);
                nextNodeRecord.setSerialNum(currApprovalRecords.get(0).getSerialNum());
                approvalRecordMapper.updateApprovalRecordBySerialNum(nextNodeRecord);
                //内部消息推送
                // sendMessage(currApprovalRecords, allApprovalRecords,sequence);
                //    消息推送
                jpushMessage(approvalRecord.getTypeOperation(),currApprovalRecords,allApprovalRecords);

            }else{
                //    修改业务表状态
                ApprovalRecord updateApprovalRecord = new ApprovalRecord();
                updateApprovalRecord.setBusinessStatus(Constants.COMPLETED);
                updateApprovalRecord.setSerialNum(approvalRecord.getSerialNum());
                updateApprovalRecord.setSequence(1);
                approvalRecordMapper.updateApprovalRecordBySerialNum(updateApprovalRecord);
                iSyTableRecordTService.updateBusinessStatus(approvalRecord.getSerialNum(),Constants.COMPLETED);
                //租赁订单审批完成创建出库单
                if (approvalRecord.getSerialNum().contains("ZLDD")){
                    outboundOrderService.createOutboundOrder(approvalRecord.getSerialNum());
                    //通知物流人员：王秋月
                    noticeLogisticsPersonnel(approvalRecord.getSerialNum());
                }
                //销售订单审批完成创建出库单，通知对应仓库的负责人和江磊，机器状态字段变更为已销售
                if (approvalRecord.getSerialNum().contains("ZLXSDD")){
                    outboundOrderService.createOutboundOrder(approvalRecord.getSerialNum());
                    //通知仓管
                    orderServiceImpl.noticeStorekeeper(approvalRecord.getSerialNum());
                    //通知物流人员：江磊
                    noticeSiloPipe();
                }
                //追加押金
                if (approvalRecord.getSerialNum().contains("ZJYJ")){
                    iSyAdditionalDepositService.addToDeposit(approvalRecord.getSerialNum());
                }
                //通知发起人
                noticeInitiator("你发起的"+approvalRecord.getSerialNum()+"订单已完成",allApprovalRecords);
            }

        } else if (Constants.REJECTED.equals(approvalRecord.getTypeOperation())) {
            //操作驳回
            //    修改当前流程记录状态：审批中->驳回
            ApprovalRecord approvalRecordParam = getApprovalRecord(approvalRecord,loginUser, currApprovalRecords,Constants.REJECT,Constants.REJECTED);
            approvalRecordMapper.updateApprovalRecordBySerialNum(approvalRecordParam);
            //   修改申请人流程记录状态：已完成->驳回
            updateApprovalRecordBySerialNum(1,approvalRecord.getSerialNum(),Constants.REJECT,loginUser.getUsername(),Constants.REJECT);
            iSyTableRecordTService.updateBusinessStatus(approvalRecord.getSerialNum(),Constants.REJECT);
            //    第三方消息推送
            jpushMessage(approvalRecord.getTypeOperation(),currApprovalRecords,allApprovalRecords);
        } else if (Constants.DEFERRED.equals(approvalRecord.getTypeOperation())){
            // 延迟操作
            //修改延迟操作意见
            ApprovalRecord deferredRecord = new ApprovalRecord();
            deferredRecord.setSequence(currApprovalRecords.get(0).getSequence());
            deferredRecord.setSerialNum(approvalRecord.getSerialNum());
            deferredRecord.setDeferredRemark(approvalRecord.getDeferredRemark());
            deferredRecord.setUpdateBy(loginUser.getUsername());
            deferredRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            approvalRecordMapper.updateApprovalRecordBySerialNum(deferredRecord);
            iSyTableRecordTService.updateBusinessStatus(approvalRecord.getSerialNum(),Constants.DEFERRED);
        } else if (Constants.RECALL.equals(approvalRecord.getTypeOperation())) {
            // 撤回
            AjaxResult recallResult = getRecallResult(approvalRecord, loginUser);
            if (recallResult != null) {
                return recallResult;
            }
            //   修改申请人流程记录状态：已完成->撤回
            updateApprovalRecordBySerialNum(1,approvalRecord.getSerialNum(),Constants.RECALL,loginUser.getUsername(),Constants.RECALL);
            //   修改当前流程记录状态：待审批->撤回
            updateApprovalRecordBySerialNum(2,approvalRecord.getSerialNum(),Constants.RECALL,loginUser.getUsername(),null);
            //    第三方消息推送
            jpushMessage(approvalRecord.getTypeOperation(),currApprovalRecords,allApprovalRecords);
            iSyTableRecordTService.updateBusinessStatus(approvalRecord.getSerialNum(),Constants.RECALL);
        } else {
            return new AjaxResult(HttpStatus.ERROR,"操作类型不匹配");
        }
        return new AjaxResult(HttpStatus.SUCCESS,"操作成功");
    }

    /**
     * 通知物流人员
     */
    private void noticeLogisticsPersonnel(String orderNo) {
        try {
            List<ApprovalConfig> approvalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("WLRY", "1"));
            if (CollectionUtils.isEmpty(approvalConfigList)) {
                throw new BaseException("请检查审批配置信息：WLRY");
            }
            List<String> registrationIdsByUserIds = jpushMapper.selectRegistrationIdsByUserIds(approvalConfigList.stream().map(ApprovalConfig::getUserId).collect(Collectors.toList()));
            if (CollectionUtils.isEmpty(registrationIdsByUserIds)){
                throw new BaseException("租赁订单审批完成-物流人员设备id不存在");
            }
            UniJpushUtils.doPost(new UniPushDomain(registrationIdsByUserIds,"湿云",orderNo+"租赁订单审批完成，请填写物流"));
        } catch (Exception e) {
            LOGGER.error("租赁订单审批完成-通知物流人员失败", e);
        }
    }

    /**
     * 通知江磊
     */
    private void noticeSiloPipe() {
        try {
            List<ApprovalConfig> approvalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("XS_ORDER_JL", "1"));
            if (CollectionUtils.isEmpty(approvalConfigList)) {
                throw new BaseException("请检查审批配置信息：XS_ORDER_JL");
            }
            List<String> registrationIdsByUserIds = jpushMapper.selectRegistrationIdsByUserIds(approvalConfigList.stream().map(ApprovalConfig::getUserId).collect(Collectors.toList()));
            if (CollectionUtils.isEmpty(registrationIdsByUserIds)){
                throw new BaseException("销售订单审批完成-江磊设备id不存在");
            }
            UniJpushUtils.doPost(new UniPushDomain(registrationIdsByUserIds,"湿云","销售订单审批完成！"));
        } catch (Exception e) {
            LOGGER.error("销售订单审批完成-通知江磊失败", e);
        }
    }

    /**
     * 第三方消息推送
     * @param typeOperation
     * @param currApprovalRecords
     * @param allApprovalRecords
     */
    private void jpushMessage(String typeOperation, List<ApprovalRecord> currApprovalRecords, List<ApprovalRecord> allApprovalRecords) {
        if (!Constants.RECALL.equals(typeOperation)){
            if (CollectionUtils.isEmpty(currApprovalRecords) || CollectionUtils.isEmpty(allApprovalRecords)){
                throw new RuntimeException("当前审批记录集合为空");
            }
        }

        try {
            //  判断类型
            if (Constants.AGREE.equals(typeOperation)){
                //    通知下一个人
                ApprovalRecord currApprovalRecord = currApprovalRecords.get(0);
                for (ApprovalRecord allApprovalRecord : allApprovalRecords) {
                    if (allApprovalRecord.getSequence()==(currApprovalRecord.getSequence()+1)){
                        List<String> agreeList = getTipsUserIds(Collections.singletonList(allApprovalRecord.getApproverId()));
                        if (CollectionUtils.isEmpty(agreeList)){
                            throw new BaseException("jpushMessage-agreeList","人员为空");
                        }
                        UniJpushUtils.doPost(new UniPushDomain(agreeList, SHI_YU,"您有新的订单需要审批！"));
                        //通知发起人
                        noticeInitiator("你发起的"+allApprovalRecord.getSerialNum()+"订单到"+allApprovalRecord.getApproverName()+"审批",allApprovalRecords);
                    }
                }
            }else if (Constants.REJECTED.equals(typeOperation)){
                String serialNum="";
                List<Long> userIds = new ArrayList<>();
                for (ApprovalRecord allApprovalRecord : allApprovalRecords) {
                    if (allApprovalRecord.getSequence()==1){
                        serialNum=allApprovalRecord.getSerialNum();
                        List<String> rejectedList = getTipsUserIds(Collections.singletonList(allApprovalRecord.getApproverId()));
                        if (!CollectionUtils.isEmpty(rejectedList)){
                            // 通知发起人
                            UniJpushUtils.doPost(new UniPushDomain(rejectedList, SHI_YU,"您有订单被驳回，请查看！"));
                        }
                    }
                    if (Constants.COMPLETED.equals(allApprovalRecord.getApprovalStatus())){
                        userIds.add(allApprovalRecord.getApproverId());
                    }
                }
                if (!CollectionUtils.isEmpty(userIds)){
                    List<String> rejectedList = getTipsUserIds(userIds);
                    if (!CollectionUtils.isEmpty(rejectedList)){
                        //通知审批过的
                        UniJpushUtils.doPost(new UniPushDomain(rejectedList, SHI_YU,serialNum+"订单被驳回，请知悉！"));
                    }
                }
            }else if (Constants.RECALL.equals(typeOperation)){
                //    通知下一个人
                // ApprovalRecord currApprovalRecord = currApprovalRecords.get(0);
                for (ApprovalRecord allApprovalRecord : allApprovalRecords) {
                    if (allApprovalRecord.getSequence()==(2)){
                        //   通知下一审批人
                        List<String> recallList = getTipsUserIds(Collections.singletonList(allApprovalRecord.getApproverId()));
                        if (!CollectionUtils.isEmpty(recallList)){
                            UniJpushUtils.doPost(new UniPushDomain(recallList, SHI_YU,allApprovalRecord.getUserName()+"撤回了订单"));
                        }
                    }
                }
            }else {
                throw new BaseException("jpushMessage","操作类型有误");
            }
        } catch (Exception e) {
            LOGGER.error("操作审批记录第三方消息推送失败",e);
        }
    }

    /**
     * 通知发起人审批进度
     * @param content
     * @param allApprovalRecords
     */
    public void noticeInitiator(String content,List<ApprovalRecord> allApprovalRecords){
    //    获取审批人id
        ApprovalRecord approvalRecord=null;
        for (ApprovalRecord allApprovalRecord : allApprovalRecords) {
            if (1==allApprovalRecord.getSequence()){
                approvalRecord=allApprovalRecord;
            }
        }
        if (Objects.nonNull(approvalRecord)){
        //    获取发起人设备id
            List<String> tipsUserIds = getTipsUserIds(Collections.singletonList(approvalRecord.getApproverId()));
        //    给发起人发送消息提示
            UniPushDomain uniPushDomain = new UniPushDomain();
            uniPushDomain.setCids(tipsUserIds);
            uniPushDomain.setTitle(SHI_YU);
            uniPushDomain.setContent(content);
            UniJpushUtils.doPost(uniPushDomain);
        }
    }

    /**
     * 获取审批id根据设备id
     * @param userIds
     * @return
     */
    private List<String> getTipsUserIds(List<Long> userIds) {
        return jpushMapper.selectRegistrationIdsByUserIds(userIds);
    }

    /**
     * 撤回前校验
     * @param approvalRecord
     * @param loginUser
     * @return
     */
    private AjaxResult getRecallResult(ApprovalRecord approvalRecord, LoginUser loginUser) {
        //获取该流水单号的所有审批记录
        List<ApprovalRecord> allApprovalRecords = getApprovalRecords(approvalRecord);
        for (ApprovalRecord record : allApprovalRecords) {
            if (record.getSequence()==null){
                return new AjaxResult(HttpStatus.ERROR, "审批单序号有误！");
            }
            //判断当前操作是否是发起人
            if (record.getSequence()==1){
                if (!loginUser.getUserId().equals(record.getApproverId())){
                    return new AjaxResult(HttpStatus.ERROR, "您不是发起人，不能撤回！");
                }
            }
            // 判断该审批单是否已审批，审批则不能撤回
            if (record.getSequence()==2){
                if(!Constants.APPROVE.equals(record.getApprovalStatus())){
                    return new AjaxResult(HttpStatus.ERROR, "该审批单已被下一节点审批，请当前审批人驳回再提交。");
                }
            }
        }
        return null;
    }

    /**
     * 修改发起人状态
     * @param sequence
     * @param serialNum
     * @param status
     * @param name
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateApprovalRecordBySerialNum(Integer sequence,String serialNum,String status,String name,String businessStatus) {
        ApprovalRecord record = new ApprovalRecord();
        record.setSequence(sequence);
        record.setSerialNum(serialNum);
        record.setApprovalStatus(status);
        record.setBusinessStatus(businessStatus);
        record.setUpdateBy(name);
        record.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        approvalRecordMapper.updateApprovalRecordBySerialNum(record);
    }

    /**
     * 消息推送
     *
     * @param approvalRecords
     * @param allApprovalRecords
     * @param sequence
     */
    private void sendMessage(List<ApprovalRecord> approvalRecords, List<ApprovalRecord> allApprovalRecords, Integer sequence) {
        try {
            //获取下一节点信息
            List<ApprovalRecord> nextNodeList = allApprovalRecords.stream().filter(a -> a.getSequence().equals(sequence)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(nextNodeList)){
                LOGGER.error("消息推送获取审批下一节点失败");
            }
            //当前审批记录
            ApprovalRecord currApprovalRecord = approvalRecords.get(0);

            Message message = new Message();
            message.setFromId(currApprovalRecord.getApproverId());
            message.setFromName(currApprovalRecord.getApproverName());
            message.setStatus(currApprovalRecord.getApprovalStatus());
            message.setSerialNum(currApprovalRecord.getSerialNum());

            //下一审批记录
            ApprovalRecord nextApprovalRecord = nextNodeList.get(0);
            message.setNextNodeId(nextApprovalRecord.getApproverId());
            message.setNextNodeName(nextApprovalRecord.getApproverName());

            LOGGER.info("推送消息："+ JSON.toJSONString(message));
            webSocketServer.onMessage(JSON.toJSONString(message));

        } catch (Exception e) {
            LOGGER.error("操作审批之后消息推送失败",e);
        }
    }

    /**
     * 获取所有审批记录
     * @param approvalRecord
     * @return
     */
    private List<ApprovalRecord> getApprovalRecords(ApprovalRecord approvalRecord) {
        ApprovalRecord allApprovalRecord;
        allApprovalRecord = new ApprovalRecord();
        allApprovalRecord.setSerialNum(approvalRecord.getSerialNum());
        List<ApprovalRecord> allApprovalRecords = approvalRecordMapper.selectApprovalRecordList(allApprovalRecord);
        return allApprovalRecords;
    }

    /**
     * 修改当前节点状态
     * @param loginUser 当前登录人信息
     * @param approvalRecords
     * @return
     */
    private static ApprovalRecord getApprovalRecord(ApprovalRecord ApprovalRecord,LoginUser loginUser, List<ApprovalRecord> approvalRecords,String status,String typeOperation) {
        ApprovalRecord approvalRecordParam = new ApprovalRecord();
        approvalRecordParam.setApprovalStatus(status);
        approvalRecordParam.setTypeOperation(typeOperation);
        approvalRecordParam.setSequence(approvalRecords.get(0).getSequence());
        approvalRecordParam.setSerialNum(approvalRecords.get(0).getSerialNum());
        approvalRecordParam.setApprovalRemark(ApprovalRecord.getApprovalRemark());
        approvalRecordParam.setRemark(ApprovalRecord.getRemark());
        approvalRecordParam.setUpdateBy(loginUser.getUsername());
        approvalRecordParam.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        return approvalRecordParam;
    }

    /**
     * 批量删除审批记录
     * 
     * @param ids 需要删除的审批记录主键
     * @return 结果
     */
    @Override
    public int deleteApprovalRecordByIds(Long[] ids)
    {
        return approvalRecordMapper.deleteApprovalRecordByIds(ids);
    }

    /**
     * 删除审批记录信息
     * 
     * @param id 审批记录主键
     * @return 结果
     */
    @Override
    public int deleteApprovalRecordById(Long id)
    {
        return approvalRecordMapper.deleteApprovalRecordById(id);
    }
}
